﻿using OpenNETCF.IoC;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;

namespace IoTCM
{
    internal partial class RequestProcessor
    {
        private void ProcessPut(HttpListenerContext context)
        {
            Debug.WriteLine("PUT: " + context.Request.Url.ToString());
        
            var host = GetRequestedHost(context);
            if (host == null)
            {
                return;
            }

            Session session;

            // first check the session
            if (!ValidateSession(context, host, out session))
            {
                return;
            }

            // check to see if user has rights to write
            if(SessionsEnabled)
            {
                if((session.Rights & UserRights.Write) != UserRights.Write)
                {
                    SendNotAuthorizedError(context, host);
                    return;
                }
            }

            if (context.Request.Url.Segments.Length < 2)
            {
                SendNotFoundError(context, host);
                return;
            }

            var entityName = context.Request.Url.Segments[1].ToLower().Replace("/", string.Empty);

            try
            {
                switch (context.Request.Url.Segments.Length)
                {
                    case 2:
                        // writing multiple values at once
                        switch (entityName)
                        {
                            case "things":
                                // you cannot write things, only values
                                SendNotAllowedError(context, host);
                                break;
                            case "values":
                                var data = GetRequestData(context);
                                WriteValues(context, host, data);
                                return;
                            default:
                                SendNotFoundError(context, host);
                                break;
                        }

                        break;
                    case 3:
                        // writing a single value
                        // get the requested ID
                        var id = context.Request.Url.Segments[2];

                        switch (entityName)
                        {
                            case "things":
                                // you cannot write things, only values
                                SendNotAllowedError(context, host);
                                break;
                            case "values":
                                var data = GetRequestData(context);
                                WriteValue(context, host, id, data);
                                return;
                            default:
                                SendNotFoundError(context, host);
                                break;
                        }
                        break;
                    default:
                        SendNotFoundError(context, host);
                        break;
                }
            }
            catch (Exception ex)
            {
                SendExceptionReturn(context, host, ex);
            }

            SendNotFoundError(context, host);
        }

        private void WriteValues(HttpListenerContext context, IHost host, string data)
        {
            var values = host.DeserializeValues(data);

            m_provider.UpdateCurrentValues(values);

            SendAcceptedResponse(context, host, string.Format("{0} values written", values.Length));
        }

        private void WriteValue(HttpListenerContext context, IHost host, string valueID, string data)
        {
            var values = host.DeserializeValues(data);

            var requested = values.First(v => v.ID == valueID);

            m_provider.UpdateCurrentValues(new DataValue[] { requested });

            SendAcceptedResponse(context, host, string.Format("{0} value written", valueID));
        }
    }
}
